-- SETUP --
local maincolor = {80/255, 64/255, 77/255}		-- mainly used for healthbar
local sndcolor = {208/255, 172/255, 146/255}	-- font color, ...
local trdcolor = {220/255, 220/255, 220/255}	-- castbar, buff/debuff borders

local mediaFolder = "Interface\\AddOns\\oUF_viv5\\media\\"	-- don't touch this ...
local HPtex = mediaFolder.."dZ"					-- health bar texture
local PPtex = mediaFolder.."dZ"					-- power bar texture
local Auratex = mediaFolder.."dBBorderH"		-- border texture for buffs/debuffs
local useIconGlow = true						-- show glow around buffs and debuffs

local glowtex = "Interface\\AddOns\\oUF_viv5\\media\\glowTex"		-- HP border texture (also used for threat highlight) -- glowTex, glowTex2, glowTex3, glowTex4 (thin > thicker)
local glowtex2 = "Interface\\AddOns\\oUF_viv5\\media\\glowTex2"		-- PP border texture (also used for debuff highlight) -- glowTex, glowTex2, glowTex3, glowTex4 (thin > thicker) 

local NameFont = mediaFolder.."BigNoodleTitling.ttf"	
local NumbFont = mediaFolder.."Prototype.ttf"	
local NameFS = 10
local NumbFS = 10 
local FontF = "THINOUTLINE" --local fontF = nil

-- END OF CONFIG --
	
local RaidScale = 1.0

-- initial frame size
local height = {
		["R"] = 32,		-- raid, party
		} 

local width = {
		["R"] = 70, 	-- raid, party
		}

-- debuff filter (raid/party only)
local DebuffBlacklist = {
	[GetSpellInfo(69127)] = true,	-- Chill of the Throne
	[GetSpellInfo(57724)] = true,	-- Sated
	[GetSpellInfo(57723)] = true,	-- Exhaustion	
	[GetSpellInfo(45769)] = true,	-- Sunwell Radiance	
	[GetSpellInfo(28786)] = true,	-- Anub'arak (Naxx) - Locust Swarm 10	
	[GetSpellInfo(54022)] = true,	-- Locust Swarm 25	
	[GetSpellInfo(66240)] = true,	-- Anub'arak (ToC) - Leeching Swarm 10	
	[GetSpellInfo(67630)] = true,	-- Leeching Swarm 25	
	[GetSpellInfo(68646)] = true,	-- Leeching Swarm 10H	
	[GetSpellInfo(68647)] = true,	-- Leeching Swarm 25H
	[GetSpellInfo(67176)] = true,	-- Twin Val'kyr Dark Essence
	[GetSpellInfo(67223)] = true,	-- Twin Val'kyr Light Essence
	[GetSpellInfo(41425)] = true,	-- Hypothermia
	[GetSpellInfo(25771)] = true,	-- Forbearance
	[GetSpellInfo(32407)] = true,	-- Strange Aura	
	[GetSpellInfo(20584)] = true,	-- Ghost (N8elf?!)
	[GetSpellInfo(8326)] = true,	-- Ghost
	[GetSpellInfo(71328)] = true,	-- Dungeon Cooldown
	[GetSpellInfo(71041)] = true,	-- Dungeon Deserter
	[GetSpellInfo(26013)] = true,	-- Deserter	
	[GetSpellInfo(55711)] = true,	-- Weakened Heart
	[GetSpellInfo(11196)] = true,	-- Recently Bandaged
	[GetSpellInfo(36032)] = true,	-- Arcane Blast
	[GetSpellInfo(48168)] = true,	-- Inner Fire
	[GetSpellInfo(57472)] = true,	-- Renewed Hope	
}

local AuraFilter = function(icons, unit, icon, name, rank, texture, count, dtype, duration, timeLeft, caster)
	local isPlayer
	if(caster == 'player' or caster == 'vehicle') then
		isPlayer = true
	end
	if((icons.onlyShowPlayer and isPlayer) or (not icons.onlyShowPlayer and name)) and not(DebuffBlacklist[name]) then
		icon.isPlayer = isPlayer
		icon.owner = caster
		return true
	end
end

-- menu
local menu = function(self)
	local unit = self.unit:sub(1, -2)
	local cunit = self.unit:gsub("(.)", string.upper, 1)

	if(unit == "party" or unit == "partypet") then
		ToggleDropDownMenu(1, nil, _G["PartyMemberFrame"..self.id.."DropDown"], "cursor", 0, 0)
	elseif(_G[cunit.."FrameDropDown"]) then
		ToggleDropDownMenu(1, nil, _G[cunit.."FrameDropDown"], "cursor", 0, 0)
	end
end

local playerClass = select(2, UnitClass("player"))	

-- priest tags
oUF.Tags["[vivPWS]"] = function(u) if UnitAura(u, GetSpellInfo(48066) or "Power Word: Shield") then return "|cffFFD800S|r" end end
oUF.Tags["[vivRenew]"] = function(u) if UnitAura(u, GetSpellInfo(48068) or "Renew") then return "|cff00FF10R|r" end end
oUF.Tags["[vivPoM]"] = function(u) local c = select(4, UnitAura(u, GetSpellInfo(48113) or "Prayer of Mending")) if c then return "|cffFFCF7FPoM("..c..")|r" end end
oUF.Tags["[vivGS]"] = function(u) if UnitAura(u, GetSpellInfo(47788) or "Guardian Spirit") then return "|cffFFD800G|r" end end

oUF.TagEvents["[vivPWS]"] = "UNIT_AURA"
oUF.TagEvents["[vivRenew]"] = "UNIT_AURA"
oUF.TagEvents["[vivPoM]"] = "UNIT_AURA"
oUF.TagEvents["[vivGS]"] = "UNIT_AURA"

-- paladin tags
oUF.Tags["[vivSacS]"] = function(u) if UnitAura(u, GetSpellInfo(53601) or "Sacred Shield") then return "|cffFFAA00SS|r" end end
oUF.Tags["[vivBoL]"] = function(u) if UnitAura(u, GetSpellInfo(53563) or "Beacon of Light") then return "|cffFFD800BoL|r" end end

oUF.TagEvents["[vivSacS]"] = "UNIT_AURA"
oUF.TagEvents["[vivBoL]"] = "UNIT_AURA"

-- druid tags
oUF.Tags["[vivRej]"] = function(u) if UnitAura(u, GetSpellInfo(48441) or "Rejuvenation") then return "|cff00FEBFRj|r" end end
oUF.Tags["[vivReg]"] = function(u) if UnitAura(u, GetSpellInfo(48443) or "Regrowth") then return "|cff00FF10Rg|r" end end
oUF.Tags["[vivLB]"] = function(u) local c = select(4, UnitAura(u, GetSpellInfo(48451) or "Lifebloom")) if c then return "|cffA7FD0ALB("..c..")|r" end end
oUF.Tags["[vivInn]"] = function(u) if UnitAura(u, GetSpellInfo(29166) or "Innervate") then return "|cff3c3be7Iv|r" end end
oUF.Tags["[vivWG]"] = function(u) if UnitAura(u, GetSpellInfo(53251) or "Wild Growth") then return "|cff33FF33WG|r" end end

oUF.TagEvents["[vivRej]"] = "UNIT_AURA"
oUF.TagEvents["[vivReg]"] = "UNIT_AURA"
oUF.TagEvents["[vivLB]"] = "UNIT_AURA"
oUF.TagEvents["[vivInn]"] = "UNIT_AURA"
oUF.TagEvents["[vivWG]"] = "UNIT_AURA"

-- shaman tags
oUF.Tags["[vivES]"] = function(u) local c = select(4, UnitAura(u, GetSpellInfo(49284) or "Earth Shield")) if c then return "|cffFFCF7FES("..c..")|r" end end
oUF.Tags["[vivRipT]"] = function(u) if UnitAura(u, GetSpellInfo(61301) or "Riptide") then return "|cff00FEBFR|r" end end
oUF.Tags["[vivErLiv]"] = function(u) if UnitAura(u, GetSpellInfo(52000) or "Earthliving") then return "|cff00FEBFErEL|r" end end

-- skinning buffs and aura functions
local function auraIcon(self, icon, icons, index, debuff)
		icons.showDebuffType = true		-- show debuff border type color 
		icon.cd.noOCC = true		 	-- hide OmniCC CDs
		icon.cd.noCooldownCount = true	-- hide CDC CDs
		icons.disableCooldown = true	-- hide CD spiral
	
		icon.count:SetFont(NumbFont, NumbFS*0.8, FontF)
		icon.count:SetPoint("TOPRIGHT", icon, 4, 12)
	
		icon.time = icon:CreateFontString(nil, 'OVERLAY')
		icon.time:SetFont(NumbFont, NumbFS*0.84, FontF)
		icon.time:SetPoint('TOP', icon, 'BOTTOM', 0, 6)
		icon.time:SetJustifyH('CENTER')
		icon.time:SetVertexColor(trdcolor[1], trdcolor[2], trdcolor[3])
		
		icon.icon:SetTexCoord(.07, .93, .07, .93)
		icon.icon:SetPoint("TOPLEFT", icon, "TOPLEFT", 2, -2)
		icon.icon:SetPoint("BOTTOMRIGHT", icon, "BOTTOMRIGHT", -2, 2)
		
		if useIconGlow == true then		
		icon.Glow = CreateFrame("Frame", nil, icon)
		icon.Glow:SetPoint("TOPLEFT", icon, "TOPLEFT", -4, 4)
		icon.Glow:SetPoint("BOTTOMRIGHT", icon, "BOTTOMRIGHT", 4, -4)
		icon.Glow:SetFrameStrata("BACKGROUND")	
		icon.Glow:SetBackdrop{edgeFile = glowtex, edgeSize = 5, insets = {left = 4, right = 4, top = 4, bottom = 4}}
		icon.Glow:SetBackdropColor(0, 0, 0, 0)
		icon.Glow:SetBackdropBorderColor(0, 0, 0)
		self.Glow:SetFrameStrata("BACKGROUND")		
		end
		
		icon.overlay:SetTexture(Auratex)
		icon.overlay:SetTexCoord(0,1,0,1)
		icon.overlay.Hide = function(self) self:SetVertexColor(trdcolor[1], trdcolor[2], trdcolor[3]) end
		--icon.overlay.Hide = function(self) self:SetVertexColor(sndcolor[1], sndcolor[2], sndcolor[3]) end
		--icon.overlay.Hide = function(self) self:SetVertexColor(maincolor[1],maincolor[2],maincolor[3]) end	
end

-- duration text
local function auraUpdateTimeShort(self, elapsed)
	self.timeLeft = math.max(self.timeLeft - elapsed, 0)
	self.time:SetText(self.timeLeft < 120 and math.floor(self.timeLeft) or '')
end

local function auraUpdateIcon(self, icons, unit, icon, index, offset, filter, isDebuff, duration, timeLeft)
	if(unit) then 
		local _, _, _, _, _, duration, timeLeft = UnitAura(unit, index, filter)

		icon.timeLeft = timeLeft - GetTime()			
		icon:SetScript('OnUpdate', auraUpdateTimeShort)	

		if duration == 0 or not timeLeft then
			icon.timeLeft = nil
			icon.time:SetText()
			icon:SetScript('OnUpdate', nil)
		end		
	end
end

-- threat highlight
local function updateThreatStatus(self, event, u)
	if (self.unit ~= u) then return end
	local s = UnitThreatSituation(u)
	if s and s > 1 then
		local r, g, b = GetThreatStatusColor(s)
		self.Glow:SetBackdropBorderColor(r, g, b, 1)
	else
		self.Glow:SetBackdropBorderColor(0, 0, 0, 1)
	end
end

-- debuff highlight
local CanDispel = {
	PRIEST = { Magic = true, Disease = true, },
	SHAMAN = { Poison = true, Disease = true, },
	PALADIN = { Magic = true, Poison = true, Disease = true, },
	MAGE = { Curse = true, },
	DRUID = { Curse = true, Poison = true, }
}
local dispellist = CanDispel[playerClass] or {}

local function GetDebuffType(unit)
	if not UnitCanAssist("player", unit) then return nil end
	local i = 1
	while true do
		local name, rank, texture, count, debufftype, duration, expirationTime, source = UnitDebuff(unit, i)
		if not texture then break end
		if debufftype and dispellist[debufftype] then
			return debufftype
		end
		i = i + 1
	end
end

local function updateDispel(self, event, u)
	if not u or self.unit ~= u then return end
	local debufftype = GetDebuffType(u)
	if debufftype then
		local color = DebuffTypeColor[debufftype] 
		self.Glow.pp:SetBackdropBorderColor(color.r, color.g, color.b, 0.8)
	else
		self.Glow.pp:SetBackdropBorderColor(0, 0, 0, 0.8)
	end
end

-- layout
local Shared = function(self, unit)
	self.menu = menu

	self:SetScript("OnEnter", UnitFrame_OnEnter)
	self:SetScript("OnLeave", UnitFrame_OnLeave)

	self:RegisterForClicks"anyup"
	self:SetAttribute("*type2", "menu")
	
	-- hp
	local hp = CreateFrame("StatusBar", nil, self)
	hp:SetHeight(height.R)
	hp:SetWidth(width.R)	
	hp:SetStatusBarTexture(HPtex)	
	hp:SetPoint("LEFT", self, "LEFT", 0, 0)	
	hp:SetStatusBarColor(maincolor[1],maincolor[2],maincolor[3])	
	hp:SetAlpha(0.8)
	--hp:SetOrientation("VERTICAL")	
	hp.frequentUpdates = true
	hp:SetFrameLevel(0.8)	
	self.Health = hp	

	hp.bg = hp:CreateTexture(nil, "BORDER")
	hp.bg:SetAllPoints(hp)
	hp.bg:SetTexture(HPtex)
	hp.bg:SetAlpha(0.4)
	hp.bg:SetVertexColor(trdcolor[1], trdcolor[2], trdcolor[3])
	
	self.Glow = CreateFrame("Frame", nil, self)
	self.Glow:SetPoint("TOPLEFT", self, "TOPLEFT", -5, 5)
	self.Glow:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", 5, -5)
	self.Glow:SetBackdrop{edgeFile = glowtex, edgeSize = 5, insets = {left = 3, right = 3, top = 3, bottom = 3}}
	self.Glow:SetBackdropColor(0, 0, 0, 0.8)
	self.Glow:SetBackdropBorderColor(0, 0, 0)	

	-- pp	
	local pp = CreateFrame("StatusBar", nil, self)
	pp:SetHeight(5)
	pp:SetWidth(width.R*0.4)
	pp:SetStatusBarTexture(PPtex)
	pp:SetPoint("BOTTOMRIGHT", hp, "BOTTOMRIGHT", -2, 0)	
	pp:SetAlpha(0.8)
	pp:SetFrameLevel(14)
	
	pp.frequentUpdates = true
	pp.colorTapping = true
	pp.colorHappiness = true
	pp.colorClass = true
	pp.colorReaction = true
	self.Power = pp	
	
	pp.bg = pp:CreateTexture(nil, "BORDER")
	pp.bg:SetAllPoints(pp)
	pp.bg:SetTexture(PPtex)
	pp.bg:SetAlpha(0.4)
	pp.bg:SetVertexColor(trdcolor[1], trdcolor[2], trdcolor[3])	
	
	self.Glow.pp = CreateFrame("Frame", nil, pp)
	self.Glow.pp:SetPoint("TOPLEFT", pp, "TOPLEFT", -5, 5)
	self.Glow.pp:SetPoint("BOTTOMRIGHT", pp, "BOTTOMRIGHT", 5, -5)
	self.Glow.pp:SetBackdrop{edgeFile = glowtex2, edgeSize = 5, insets = {left = 3, right = 3, top = 3, bottom = 3}}
	self.Glow.pp:SetBackdropColor(0, 0, 0, 0.8)
	self.Glow.pp:SetBackdropBorderColor(0, 0, 0)	
	
	-- font strings	
	self.Name = hp:CreateFontString(nil, "ARTWORK")
	self.Name:SetFont(NumbFont, NumbFS, FontF)
	self:Tag(self.Name, '[raidcolor][raidhpname]')	
	
	local PriestTags = "[vivPWS( )][vivRenew( )][vivPoM( )][vivGS( )]"
	local PaladinTags = "[vivSacS( )][vivBoL( )]"
	local DruidTags = "[vivRej( )][vivReg( )][vivLB( )][vivWG( )][vivInn( )]"
	local ShamanTags = "[vivES( )][vivRipT( )][vivErLiv()]]"	
	self.Text = hp:CreateFontString(nil, "ARTWORK")
	self.Text:SetFont(NumbFont, NumbFS*0.7, FontF)
	self.Text:SetTextColor(sndcolor[1], sndcolor[2], sndcolor[3])	
	self.Text:SetHeight(height.R*0.7)
	self.Text:SetWidth(width.R*0.4)
	
	if IsAddOnLoaded("oUF_SpellRange") then	
		if(unit) or (self:GetParent():GetName():match"oUF_Raid") then 
		self.SpellRange = true; -- fadeout if units are out of range
		self.inRangeAlpha = 1.0; -- Frame alpha when in range
		self.outsideRangeAlpha = 0.3; -- Frame alpha when out of range
		end	
	end
	
	if IsAddOnLoaded("oUF_HealComm4") then			
	HCB = CreateFrame('StatusBar', nil, hp)
	HCB:SetStatusBarTexture(HPtex)
	HCB:SetStatusBarColor(0, 1, 0, 0.4)
	HCB:SetPoint('LEFT', hp, 'LEFT')
	self.HealCommBar = HCB
	self.allowHealCommOverflow = false
	self.HealCommOthersOnly = true
	end
	
	-- raid icons
	RI = self.Glow:CreateTexture(nil, "OVERLAY")
	RI:SetTexture("Interface\\TargetingFrame\\UI-RaidTargetingIcons")
	RI:SetHeight(12)
	RI:SetWidth(12)
    RI:SetPoint("BOTTOMLEFT", hp, "TOPLEFT", width.R*(2/3), -6)
	self.RaidIcon = RI	
	
	if(self:GetParent():GetName():match"oUF_Raid") then
		self.Name:SetPoint("TOPLEFT", hp, "TOPLEFT", 2, -2)
		self.Text:SetPoint("BOTTOMRIGHT", pp, "TOPRIGHT", 2, 2)			
		
		if playerClass == "PRIEST" then			
			self:Tag(self.Text, PriestTags)
		elseif playerClass == "PALADIN" then			
			self:Tag(self.Text, PaladinTags)
		elseif playerClass == "DRUID" then			
			self:Tag(self.Text, DruidTags)
		elseif playerClass == "SHAMAN" then
			self:Tag(self.Text, ShamanTags) 			
		else
			self:Tag(self.Text, " ")
		end
		
		self.Debuffs = CreateFrame("Frame", nil, self)
		self.Debuffs.initialAnchor = "BOTTOMLEFT"
		self.Debuffs.size = height.R/2		
		self.Debuffs['growth-x'] = 'RIGHT'	
		self.Debuffs:SetHeight(self.Debuffs.size)
		self.Debuffs:SetWidth(self.Debuffs.size*4)
		self.Debuffs.num = 2	
		self.Debuffs.spacing = 1
		self.Debuffs:SetPoint("BOTTOMLEFT", hp, "BOTTOMLEFT", 2, 2)
		
		self.ReadyCheck = hp:CreateTexture(nil, 'OVERLAY')
		self.ReadyCheck:SetPoint('CENTER', hp, 0, 0)
		self.ReadyCheck:SetHeight(16)
		self.ReadyCheck:SetWidth(16)
	
		self.CustomAuraFilter = AuraFilter
		self:SetAttribute('initial-scale', RaidScale)			
		self:SetAttribute("initial-height", height.R)
		self:SetAttribute("initial-width", width.R)
	end
	
	self.PostCreateAuraIcon = auraIcon
	self.PostUpdateAuraIcon = auraUpdateIcon	
	
	self:RegisterEvent("UNIT_THREAT_LIST_UPDATE", updateThreatStatus)
	self:RegisterEvent("UNIT_THREAT_SITUATION_UPDATE", updateThreatStatus)
	self:RegisterEvent("UNIT_AURA", updateDispel)	
	return self 	
end

-- spawn them ...
oUF:RegisterStyle("oUF_viv5_group", Shared)
oUF:SetActiveStyle"oUF_viv5_group"

local raid = {}
	for i = 1, 8 do
	table.insert(raid, oUF:Spawn("header", "oUF_Raid"..i))
	raid[i]:SetManyAttributes(
	'showPlayer', true,
	'showSolo', false,
	'showParty', true,
	'showRaid', true,
	'xoffset', 4,
	'yOffset', 0,
	'point', "LEFT",
	'groupFilter', i
	)
	raid[i]:Show()	
	if i == 1 then
	raid[i]:SetPoint("TOPRIGHT", oUF_Player, "TOPLEFT", -20, 0)
	else
	raid[i]:SetPoint("BOTTOMRIGHT", raid[i-1], "TOPRIGHT", 0, 4)    
	end
end